package misc

import (
	"crypto/md5"
	"dhfshop/controllers/base"
	"dhfshop/models/consts"
	"dhfshop/models/misc"
	"dhfshop/service/redisgo"
	"dhfshop/utils/helper"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/validation"
	"strings"
	"time"
)

type WxAppCfgController struct {
	base.BaseController
}

func (this *WxAppCfgController) GetQueryParaMd5() (map[string]string, map[string]string, []string, map[string]string, int, int, string, error) {
	var paraStr string
	query := make(map[string]string)
	subquery := make(map[string]string)
	fields := []string{}
	order_by := make(map[string]string)
	offset := 0 //default is 0
	limit := 10 //default is 50
	v := struct {
		Fields        string `form:"fields"`
		PageSize      int    `form:"page_size"`
		PageNo        int    `form:"page_no"`
		StartCreated  string `form:"start_created"` //
		EndCreated    string `form:"end_created"`
		StartSourceAt string `form:"start_source_at"` //
		EndSourceAt   string `form:"end_source_at"`
		Name          string `form:"name"`  //
		Query         string `form:"query"` //
		Subquery      string `form:"subquery"`
		OrderBy       string `form:"order_by"`
	}{PageSize: 10, PageNo: 1}
	this.ParseForm(&v)
	valid := validation.Validation{}
	valid.Range(v.PageSize, 1, 1000, "page_size")
	valid.Range(v.PageNo, 1, 1000, "page_no")
	passed, _ := valid.Valid(&v)
	if !passed {
		err := errors.New(valid.Errors[0].Key + " " + valid.Errors[0].Message)
		return query, subquery, fields, order_by, offset, limit, paraStr, err
	}
	v.PageNo = v.PageNo - 1 //为了计算offset
	if len(v.Fields) > 2 {
		fields = strings.Split(v.Fields, ",")
	}
	//beego.Debug("PeriodList Query", v.Query)
	if len(v.Query) > 2 {
		for _, cond := range strings.Split(v.Query, ",") {
			kv := strings.Split(cond, ":")
			if len(kv) != 2 {
				err := errors.New("Error: invalid query key/value pair")
				return query, subquery, fields, order_by, offset, limit, paraStr, err
			}
			k, v := kv[0], kv[1]
			query[k] = v
		}
	}
	if len(v.StartCreated) == 19 {
		if startCreatedTime, err := time.Parse(consts.DATETIME_FORMAT, v.StartCreated); err == nil {
			query["start_created"] = startCreatedTime.Format(consts.DATELINKTIME_FORMAT)
		}
	}
	if len(v.EndCreated) == 19 {
		if endCreatedTime, err := time.Parse(consts.DATETIME_FORMAT, v.EndCreated); err == nil {
			query["end_created"] = endCreatedTime.Format(consts.DATELINKTIME_FORMAT)
		}
	}
	if len(v.StartSourceAt) == 10 {
		query["start_source_at"] = v.StartSourceAt
	}
	if len(v.EndSourceAt) == 10 {
		query["end_source_at"] = v.EndSourceAt
	}
	if len(v.Name) > 0 {
		query["title.icontains"] = v.Name //似乎目前只有商品会用到
	}
	if len(v.Subquery) > 2 {
		for _, cond := range strings.Split(v.Subquery, ",") {
			kv := strings.Split(cond, ":")
			if len(kv) != 2 {
				err := errors.New("Error: invalid subquery key/value pair")
				return query, subquery, fields, order_by, offset, limit, paraStr, err
			}
			k, v := kv[0], kv[1]
			subquery[k] = v
		}
	}
	if len(v.OrderBy) > 2 {
		for _, cond := range strings.Split(v.OrderBy, ",") {
			kv := strings.Split(cond, ":")
			if len(kv) != 2 {
				err := errors.New("Error: invalid order_by key/value pair")
				return query, subquery, fields, order_by, offset, limit, paraStr, err
			}
			k, v := kv[0], kv[1]
			order_by[k] = v
		}
	}
	offset = v.PageNo * v.PageSize
	limit = v.PageSize
	req := struct {
		Fields   string `json:"Fields"`
		PageSize int    `json:"PageSize"`
		PageNo   int    `json:"PageNo"`
		Query    string `json:"Query"`
		OrderBy  string `json:"OrderBy"`
	}{v.Fields, v.PageSize, v.PageNo, v.Query, v.OrderBy}
	if reqJson, err := json.Marshal(&req); err == nil {
		paraStr = string(reqJson)
	}
	hash := md5.New()
	hash.Write([]byte(paraStr))
	result := fmt.Sprintf("%x", hash.Sum(nil))
	return query, subquery, fields, order_by, offset, limit, result, nil
}

func (this *WxAppCfgController) List() {
	query, _, fields, order_by, offset, limit, md5Str, err := this.GetQueryParaMd5()
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	var allowStoreId []int64
	cacheKey := md5Str
	var wxAppCfgList []*misc.WxAppCfg
	redisconn := redisgo.GetInstance()
	if cacheValue, err := redisconn.GetString(cacheKey); err == nil && len(cacheValue) > 20 {
		//beego.Debug("cache wxAppCfgList", cacheValue)
		if err = json.Unmarshal([]byte(cacheValue), wxAppCfgList); err == nil {
			rsp := struct {
				TotalCount int              `json:"total_count"`
				WxAppCfg   []*misc.WxAppCfg `json:"wxappcfg"`
			}{TotalCount: len(wxAppCfgList), WxAppCfg: wxAppCfgList}
			this.Data["json"] = rsp
			this.ServeJSON()
			return
		}
	}
	wxcfgList, cnt, err := misc.GetAllWxAppCfgs(allowStoreId, query, fields, order_by, offset, limit)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	if wxcfgListJson, err := json.Marshal(wxcfgList); err == nil {
		if _, err = redisconn.Set(cacheKey, string(wxcfgListJson), 600); err != nil {
			beego.Debug("SETEX", err.Error())
		}
	}
	rsp := struct {
		TotalCount int64            `json:"total_count"`
		WxAppCfg   []*misc.WxAppCfg `json:"wxappcfg"`
	}{TotalCount: cnt, WxAppCfg: wxcfgList}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *WxAppCfgController) Post() {
	var v misc.WxAppCfg
	valid := validation.Validation{}
	this.ParseForm(&v)
	v.PartnerId = int64(this.Ctx.Input.GetData("curCompanyId").(int))
	//v.UserId = this.Ctx.Input.GetData("curUserId").(int)
	valid.Required(v.StoreId, "store_id")
	valid.Required(v.AppId, "app_id")
	valid.Required(v.Types, "types")
	valid.Required(v.Name, "name")
	valid.Required(v.Value, "value")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key + " " + valid.Errors[0].Message)
		return
	}
	_, err := misc.CreateWxAppCfg(&v)
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	rsp := struct {
		AppId   string    `json:"app_id"`
		Created time.Time `json:"created"`
	}{AppId: v.AppId, Created: time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *WxAppCfgController) Put() {
	v := misc.WxAppCfg{}
	this.ParseForm(&v)
	v.PartnerId = int64(this.Ctx.Input.GetData("curCompanyId").(int))
	curSysRoleId := this.Ctx.Input.GetData("curRoleId").(int)
	valid := validation.Validation{}
	valid.Required(v.StoreId, "store_id")
	valid.Required(v.AppId, "app_id")
	valid.Required(v.Name, "name")
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key + " " + valid.Errors[0].Message)
		return
	}
	if curSysRoleId == 2 {
		if !this.CurrentUser.Admin {
			var allowStoreId []int64
			if this.CurrentUser != nil {
				allowStoreId = this.CurrentUser.AllowStoreId
			}
			beego.Debug("wxcfg,allowstoreid:", allowStoreId, "store_id:", v.StoreId)
			if _, err := helper.Contains(v.StoreId, allowStoreId); err != nil {
				this.ServeError("权限不足,请配置相关权限")
				beego.Debug("error:", err.Error())
				return
			}
		}
	}
	updateFields, err := this.GetUpdateFields(v, "", "form", []string{"wxapp_cfg_id"})
	if err != nil {
		this.ServeError(err.Error())
		return
	}
	//beego.Debug(v.StoreId, v.AppId, v.Name, strings.Join(updateFields, ","))
	if len(updateFields) > 0 {
		if err := misc.UpdateWxAppCfgByAppId(&v, updateFields...); err != nil {
			this.ServeError(err.Error())
			return
		}
	}
	rsp := struct {
		AppId    string    `json:"app_id"`
		Modified time.Time `json:"modified"`
	}{AppId: v.AppId, Modified: time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}

func (this *WxAppCfgController) Delete() {
	v := struct {
		AppId string `form:"app_id" valid:"Required"`
		Key   string `form:"key" valid:"Required"`
	}{}
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key + " " + valid.Errors[0].Message)
		return
	}
	if err := misc.DeleteWxAppCfgByAppId(v.AppId, v.Key); err != nil {
		this.ServeError(err.Error())
		return
	}
	rsp := struct {
		AppId    string    `json:"app_id"`
		Key      string    `json:"key"`
		Modified time.Time `json:"modified"`
	}{AppId: v.AppId, Key: v.Key, Modified: time.Now().UTC()}
	this.Data["json"] = rsp
	this.ServeJSON()
}
